/******************************************************************************
  FILE        : Display.c
  PURPOSE     : Controla diplay de 7 segmentos por 4, 8.8.8.8.
  FUNCTIONS   :
  
  DISP_init()     Inicializa puertos y valores del diplay
  DISP_setVal(V)   Muestra un entero V en display
  DISP_setUpVal(V)  Muestra un char V en los 2 primeros digitos (VVxx)
  DISP_setDownVal(V) Muestra un char V en los 2 ultimos digitos  (xxVV)
  DISP_setUpBCD(BCD)  Decompila BCD a decimal en los 2 primeros digitos
  DISP_setUpBCD(BCD) Decompila BCD a decimal en los 2 ultimos digitos
  
  
  LANGUAGE    : ANSI-C
  ----------------------------------------------------------------------------
  HISTORY 
  
******************************************************************************/

#include <MC68HC908JK3.h>
#include "display.h"
#include "bits.h"

static void pause (unsigned int time);
/***************************************************************************
 CONFIGURACION:
 Definicion de puertos de control, datos y timer para refresco
 (ver registros en la hoja de datos del fabricante)
****************************************************************************/

#define DATA    PTD       // Puerto para datos, para el valor en cada segmento.
#define DIRDATA DDRD      // Direccion del puerto de datos.
#define DRV     PTB       // Puerto de manejo para cada uno de los segmentos.
#define DIRDRV  DDRB      // Direccion del puerto de manejo.
#define COUNTH  TMODH     // Contador para Timer de refresco. Byte alto
#define COUNTL  TMODL     // Contador para Timer de refresco. Byte bajo
#define TSETUP  TSC       // TIM setup
#define TOF     TSC_TOF   // Rebusqueda del contador para timer de refresco.

#define KPULLON   { PTB_PTB6 = 1;} // Pin para muestreo 
#define KPULLOFF  { PTB_PTB6 = 0;} // del teclado.

#define TBLNK   120     // Parpadeo para configuracion (blink)
#define SGMENTS 6
                          // (Bits para manejo de los segmentos)
#define FDIGIT  0x20      // Primer digito a mostrar 
#define LDIGIT  0x00      // Ultimo digito a mostrar-1
/*****************************************************************************/


/**************************************
 Arreglo con los numeros en binario 
 del 0 al 9 para 4 leds en linea, 
 los cuales encienden con 0.
 **************************************/

const unsigned char  convert[10] = {
  0b111111,  // 0
  0b111011,  // 1
  0b110111,  // 2
  0b110011,  // ...
  0b101111,
  0b101011,
  0b100111,
  0b100011,
  0b011111,
  0b011011   // 9
};


unsigned char     buffer[SGMENTS];
unsigned char     digit=FDIGIT;
unsigned char     disp_pos=0;
unsigned char     inputkey=0;
unsigned char     blink=0;
unsigned int      tblink=0;


void DISP_init (void) {
  DIRDATA  = 0xFF;         // Puerto de dato todo como salida
  DIRDRV   = 0xFF;         // Inicialmente todo de entrada. Ver despues.
  /*
  COUNTH  = 0x03;         // Refresco a un mili segundo:  
  COUNTL  = 0xE8;         // TMOD=1000 (3E8h) con FC 4Mhz
  TSETUP  = 0x50;         // Prescaler=0 (Divisor de bus en 1).
  */
  COUNTH  = 0x07;         // Refresco a un mili segundo:  
  COUNTL  = 0xD0;         // TMOD=2000 (7D0h) con FC 8mhz
  TSETUP  = 0x50;         // Prescaler=0 (Divisor de bus en 1).

  KPULLOFF;

  buffer[0] = 0b111111;         // Inicializo todos los leds
  buffer[1] = 0b111111;
  buffer[2] = 0b111111;
  buffer[3] = 0b111111;
  buffer[4] = 0b111111;
  buffer[5] = 0b111111;

  pause(10);
}

void DISP_setVal (unsigned int V){
  buffer[0]=convert[V%10];
  buffer[1]=convert[(V%100)/10];
  buffer[2]=convert[(V%1000)/100];
  buffer[3]=convert[V/1000];
}

void DISP_setUpVal (unsigned char V){
  buffer[2]=convert[V%10];
  buffer[3]=convert[V/10];
}

void DISP_setDownVal (unsigned char V){
  buffer[0]=convert[V%10];
  buffer[1]=convert[V/10];
}

void DISP_setUpBCD (unsigned char V){
  buffer[2]=convert[V&0x0F];
  V>>=4;
  buffer[3]=convert[V];
}

void DISP_setDownBCD (unsigned char V){
  buffer[0]=convert[V&0x0F];
  V>>=4;
  buffer[1]=convert[V];
}

void DispSec(unsigned char V){
  buffer[5]=convert[V&0x0F];
  V>>=4;
  buffer[4]=convert[V];
}

void DispMin(unsigned char V){
  buffer[3]=convert[V&0x0F];
  V>>=4;
  buffer[2]=convert[V];
}

void DispHor(unsigned char V){
  buffer[1]=convert[V&0x0F];
  V>>=4;
  buffer[0]=convert[V];
}

unsigned char DISP_getkey(void){ 
  return inputkey;
}

void DISP_setBlink (unsigned char m){
  blink=m; 
}


/*void DISP_refresh(void){
  if(digit==LDIGIT) digit=FDIGIT;     // Determina que display mostrar
  if(disp_pos==SGMENTS) disp_pos=0;  // Extrae del buffer el contenido de cada display 
  DATA = buffer [disp_pos++];   // Cargo contenido
  DRV = digit;
  digit>>=1;
}*/


/*******************************************************************
 FUNCION DE REFRESCO POR INTERRUPCION DE TIMER
*******************************************************************/

interrupt 6 void Tim2_sensor_isr (void){
  if(digit==LDIGIT) digit=FDIGIT;     // Determina que display mostrar
  if(disp_pos==SGMENTS) disp_pos=0;   // Extrae del buffer el contenido de cada display 
  DATA=buffer [disp_pos++];           // Cargo numero a mostrar
  DIRDRV = ((DIRDRV&0xC0)|digit);     // * Configuro salida sin afectar i2c (PTD6-7)
  
  /*if(tblink<TBLNK&&blink){
   switch (blink){
    case (1):
    DIRDRV=DIRDRV&0xF3;
    break;
    case (2):
    DIRDRV=DIRDRV&0xCF;
    break;
   }
   tblink++;
  }else{
   if(tblink==(TBLNK+1)&&blink)tblink=0;
   if(tblink==TBLNK&&blink)tblink=TBLNK*5;
   if(tblink>TBLNK&&blink)tblink--;
  }*/
  
  DRV = ((DRV&0xC0)|digit);             // * Enmascaro para no afectar pines para i2c
  
  //if(digit==0x04){          // Muestreo para teclado, solo pines PTD(5-3)
  // KPULLON;             // Activo pin de salida en alto para muestrear.
  // inputkey = ((DRV & ~digit)&0x38); // Cargo tecla
  // KPULLOFF;             // Desactivo pin de muestreo
  //}
  
  digit>>=1;            // Siguiente bit (digito)
  TOF=0;              // Inicializo timer
}

static void pause (unsigned int time){
  unsigned int i;
  for (i=0;i<time;i++) continue;
}

